﻿using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Data;
using Windows.UI.Xaml.Media;

namespace Windows8Accelerator.Core.Xaml.Controls
{
    [TemplatePart(Name = "ListViewBase", Type = typeof(ListViewBase))]
    public class ListViewBaseContentControl : ContentControl
    {
        private ListViewBase _ListViewBase;

        public ListViewBaseContentControl()
        {
            SelectedItems.CollectionChanged += SelectedItems_CollectionChanged;
        }

        private bool _SelfUpdating;

        void SelectedItems_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
        {
            if (_ListViewBase != null && !_SelfUpdating)
            {
                _SelfUpdating = true;
                if (SelectionMode == ListViewSelectionMode.Extended || SelectionMode == ListViewSelectionMode.Multiple)
                {
                    if (e.NewItems!=null)
                        foreach (var item in e.NewItems)
                            if (!_ListViewBase.SelectedItems.Contains(item))
                                _ListViewBase.SelectedItems.Add(item);
                    if (e.OldItems != null)
                        foreach (var item in e.OldItems)
                            _ListViewBase.SelectedItems.Remove(item);
                    if (e.Action == System.Collections.Specialized.NotifyCollectionChangedAction.Reset)
                    {
                        _ListViewBase.SelectedItems.Clear();
                        foreach (var item in SelectedItems)
                            _ListViewBase.SelectedItems.Add(item);
                    }
                }
                _SelfUpdating = false;
            }
        }

        public DataTemplateSelector ItemTemplateSelector
        {
            get { return (DataTemplateSelector)GetValue(ItemTemplateSelectorProperty); }
            set { SetValue(ItemTemplateSelectorProperty, value); }
        }
        public static readonly DependencyProperty ItemTemplateSelectorProperty =
            DependencyProperty.Register("ItemTemplateSelector", typeof(DataTemplateSelector), typeof(ListViewBaseContentControl), new PropertyMetadata(null));

        public ListViewSelectionMode SelectionMode
        {
            get { return (ListViewSelectionMode)GetValue(SelectionModeProperty); }
            set { SetValue(SelectionModeProperty, value); }
        }
        public static readonly DependencyProperty SelectionModeProperty =
            DependencyProperty.Register("SelectionMode", typeof(ListViewSelectionMode), typeof(ListViewBaseContentControl), new PropertyMetadata(ListViewSelectionMode.Single, OnSelectionModePropertyChanged));

        private static void OnSelectionModePropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            var control = d as ListViewBaseContentControl;
            switch (((ListViewSelectionMode)e.NewValue))
            {
                case ListViewSelectionMode.None:
                default:
                    control.InternalSelectionMode = Windows.UI.Xaml.Controls.ListViewSelectionMode.None;
                    break;
                case ListViewSelectionMode.Single:
                    control.InternalSelectionMode = Windows.UI.Xaml.Controls.ListViewSelectionMode.Single;
                    break;
                case ListViewSelectionMode.Multiple:
                    control.InternalSelectionMode = Windows.UI.Xaml.Controls.ListViewSelectionMode.Multiple;
                    break;
                case ListViewSelectionMode.Extended:
                    control.InternalSelectionMode = Windows.UI.Xaml.Controls.ListViewSelectionMode.Extended;
                    break;
            }
        }

        public Windows.UI.Xaml.Controls.ListViewSelectionMode InternalSelectionMode
        {
            get { return (Windows.UI.Xaml.Controls.ListViewSelectionMode)GetValue(InternalSelectionModeProperty); }
            private set { SetValue(InternalSelectionModeProperty, value); }
        }
        public static readonly DependencyProperty InternalSelectionModeProperty =
            DependencyProperty.Register("InternalSelectionMode", typeof(Windows.UI.Xaml.Controls.ListViewSelectionMode), typeof(ListViewBaseContentControl), new PropertyMetadata(Windows.UI.Xaml.Controls.ListViewSelectionMode.Single));

        protected override void OnApplyTemplate()
        {
            base.OnApplyTemplate();

            _ListViewBase = GetTemplateChild("ListViewBase") as ListViewBase;
            if (_ListViewBase != null)
            {
                _ListViewBase.SelectedItem = SelectedItem;
                if (SelectionMode == ListViewSelectionMode.Extended || SelectionMode == ListViewSelectionMode.Multiple)
                {
                    if (SelectedItem != null && !_ListViewBase.SelectedItems.Contains(SelectedItem))
                        _ListViewBase.SelectedItems.Add(SelectedItem);
                    foreach (var item in SelectedItems.Where((o) => !_ListViewBase.SelectedItems.Contains(o)))
                        _ListViewBase.SelectedItems.Add(item);
                    foreach (var item in _ListViewBase.SelectedItems.Where((o) => !SelectedItems.Contains(o) && o != SelectedItem))
                        _ListViewBase.SelectedItems.Remove(item);
                }
                _ListViewBase.SelectionChanged += _ListViewBase_SelectionChanged;
                _ListViewBase.ItemClick += _ListViewBase_ItemClick;
            }
        }

        void _ListViewBase_ItemClick(object sender, ItemClickEventArgs e)
        {
            if (ItemClick != null)
                ItemClick(sender, e);
        }

        public event ItemClickEventHandler ItemClick;

        void _ListViewBase_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            if (!_SelfUpdating)
            {
                _SelfUpdating = true;
                if (e.AddedItems.Count > 0)
                    SelectedItem = e.AddedItems[0];
                else
                    SelectedItem = null;
                if (SelectionMode == ListViewSelectionMode.Extended || SelectionMode == ListViewSelectionMode.Multiple)
                {
                    foreach (var item in e.AddedItems.Where((o) => !SelectedItems.Contains(o)))
                        SelectedItems.Add(item);
                    foreach (var item in e.RemovedItems)
                        SelectedItems.Remove(item);
                }
                _SelfUpdating = false;
            }

            if (SelectionChanged != null)
                SelectionChanged(sender, e);
        }

        public event SelectionChangedEventHandler SelectionChanged;

        public object SelectedItem
        {
            get { return (object)GetValue(SelectedItemProperty); }
            set 
            { 
                SetValue(SelectedItemProperty, value);
                if (_ListViewBase != null && !_SelfUpdating)
                {
                    _SelfUpdating = true;
                    _ListViewBase.SelectedItem = value;
                    if (SelectionMode == ListViewSelectionMode.Extended || SelectionMode == ListViewSelectionMode.Multiple)
                    {
                        if (value != null)
                            _ListViewBase.SelectedItems.Add(value);
                    }
                    _SelfUpdating = false;
                    _ListViewBase.ScrollIntoView(value);
                }
            }
        }
        public static readonly DependencyProperty SelectedItemProperty =
            DependencyProperty.Register("SelectedItem", typeof(object), typeof(ListViewBaseContentControl), new PropertyMetadata(null));

        private ObservableCollection<object> _SelectedItems = new ObservableCollection<object>();

        public ObservableCollection<object> SelectedItems
        {
            get { return _SelectedItems; }
        }

        public DataTemplate ItemTemplate
        {
            get { return (DataTemplate)GetValue(ItemTemplateProperty); }
            set { SetValue(ItemTemplateProperty, value); }
        }
        public static readonly DependencyProperty ItemTemplateProperty =
            DependencyProperty.Register("ItemTemplate", typeof(DataTemplate), typeof(ListViewBaseContentControl), new PropertyMetadata(null));


        public DataTemplate GroupHeaderTemplate
        {
            get { return (DataTemplate)GetValue(GroupHeaderTemplateProperty); }
            set { SetValue(GroupHeaderTemplateProperty, value); }
        }
        public static readonly DependencyProperty GroupHeaderTemplateProperty =
            DependencyProperty.Register("GroupHeaderTemplate", typeof(DataTemplate), typeof(ListViewBaseContentControl), new PropertyMetadata(null));


        public void ScrollIntoView(object item)
        {
            if (_ListViewBase != null && item != null)
            {
                _ListViewBase.ScrollIntoView(item);
            }
        }

        public object GetFirstVisibleItem()
        {
            return VisualTreeHelper.FindElementsInHostCoordinates(
                new Windows.Foundation.Rect(0, 0, _ListViewBase.ActualWidth, _ListViewBase.ActualHeight),
                _ListViewBase)
                .Where((fe) => fe is FrameworkElement)
                .Select((fe) => ((FrameworkElement)fe).DataContext)
                .Select((dc) =>
                    {
                        if (dc is ICollectionViewGroup)
                        {
                            var cg = (ICollectionViewGroup)dc;
                            if (cg.GroupItems != null)
                                return cg.GroupItems.FirstOrDefault();
                            else
                                return cg.Group;
                        }
                        return dc;
                    }).FirstOrDefault();
        }

        public object GetFirstVisibleGroup()
        {
            var firstVisibleGroup = VisualTreeHelper.FindElementsInHostCoordinates(
                new Windows.Foundation.Rect(0, 0, _ListViewBase.ActualWidth, _ListViewBase.ActualHeight),
                _ListViewBase)
                .Where((fe) => fe is FrameworkElement)
                .Select((fe) => ((FrameworkElement)fe).DataContext)
                .Where((dc) => dc is ICollectionViewGroup)
                .Select((dc) => ((ICollectionViewGroup)dc).Group)
                .FirstOrDefault();
            return firstVisibleGroup;
        }

        public ItemsPanelTemplate DynamicItemsPanelTemplate
        {
            get { return (ItemsPanelTemplate)GetValue(DynamicItemsPanelTemplateProperty); }
            set { SetValue(DynamicItemsPanelTemplateProperty, value); }
        }
        public static readonly DependencyProperty DynamicItemsPanelTemplateProperty =
            DependencyProperty.Register("DynamicItemsPanelTemplate", typeof(ItemsPanelTemplate), typeof(ListViewBaseContentControl), new PropertyMetadata(null));



        public Style DynamicItemContainerStyle
        {
            get { return (Style)GetValue(DynamicItemContainerStyleProperty); }
            set { SetValue(DynamicItemContainerStyleProperty, value); }
        }
        public static readonly DependencyProperty DynamicItemContainerStyleProperty =
            DependencyProperty.Register("DynamicItemContainerStyle", typeof(Style), typeof(ListViewBaseContentControl), new PropertyMetadata(null));

        
    }
}
